#include <iostream>
#include <pthread.h>
#include <string>
#include <unistd.h>
#include <cassert>

using namespace std;

#define THREAD_NUM 5

int tickets = 1000;
// pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;

class ThreadData
{
public:
    ThreadData(const string& str, pthread_mutex_t* mtx)
        :_str(str),
        _mtx(mtx)
    {}

    string _str;
    pthread_mutex_t* _mtx;
};

void* handler(void* args)
{
    ThreadData* td = ((ThreadData*)args);
    string str = td->_str;
    pthread_mutex_t* mtx = td->_mtx;

    while(true)
    {
        int n = pthread_mutex_lock(mtx);
        assert(!n);
        if(tickets > 0)
        {
            usleep(1000);
            cout << str  << ":" << tickets << endl;
            --tickets;
            pthread_mutex_unlock(mtx);
        }
        else{
            pthread_mutex_unlock(mtx);
            break;
        }
        usleep(1000);
    }


    delete td;
    return nullptr;
}

int main()
{
    pthread_mutex_t mutex;
    int n = pthread_mutex_init(&mutex, nullptr);
    cout << n << endl;
    assert(!n);
    pthread_t t[THREAD_NUM];
    for(int i = 0; i < THREAD_NUM; ++i)
    {
        string str = "thread ";
        str += to_string(i + 1);
        ThreadData* TD = new ThreadData(str, &mutex);

        pthread_create(t+i, nullptr, handler, (void*)TD);
    }

    for(int i = 0; i < THREAD_NUM; ++i)
    {
        pthread_join(t[i], nullptr);
    }

    return 0;
}